package com.chat.service;

import com.chat.model.ChatMessage;
import com.chat.model.UserSession;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * 聊天服务类
 * 负责用户会话管理、消息广播、在线用户管理等核心业务逻辑
 */
@Service
public class ChatService {
    
    private static final Logger logger = Logger.getLogger(ChatService.class.getName());
    
    /**
     * 活跃的用户会话映射 (sessionId -> UserSession)
     */
    private final Map<String, UserSession> activeSessions = new ConcurrentHashMap<>();
    
    /**
     * 用户名到会话ID的映射 (username -> sessionId)
     */
    private final Map<String, String> usernameToSessionId = new ConcurrentHashMap<>();
    
    /**
     * 消息历史记录（内存存储，最多保存100条）
     */
    private final List<ChatMessage> messageHistory = Collections.synchronizedList(new ArrayList<>());
    
    /**
     * 最大消息历史记录数
     */
    private static final int MAX_MESSAGE_HISTORY = 100;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * 添加WebSocket会话
     */
    public void addSession(WebSocketSession session) {
        String sessionId = session.getId();
        UserSession userSession = new UserSession();
        userSession.setSessionId(sessionId);
        userSession.setWebSocketSession(session);
        
        activeSessions.put(sessionId, userSession);
        logger.info("会话已添加: " + sessionId);
    }
    
    /**
     * 处理用户加入聊天室
     */
    public void handleUserJoin(WebSocketSession session, String username) {
        String sessionId = session.getId();
        UserSession userSession = activeSessions.get(sessionId);
        
        if (userSession != null) {
            // 检查用户名是否已被使用
            if (usernameToSessionId.containsKey(username)) {
                sendErrorMessage(session, "用户名已被使用，请选择其他用户名");
                return;
            }
            
            // 设置用户名
            userSession.setUsername(username);
            usernameToSessionId.put(username, sessionId);
            
            // 创建加入消息
            ChatMessage joinMessage = ChatMessage.createJoinMessage(username);
            addToMessageHistory(joinMessage);
            
            // 广播用户加入消息
            broadcastMessage(joinMessage);
            
            // 发送历史消息给新用户
            sendMessageHistory(session);
            
            // 广播更新的用户列表
            broadcastUserList();
            
            logger.info("用户加入: " + username + " (会话: " + sessionId + ")");
        }
    }
    
    /**
     * 处理聊天消息
     */
    public void handleChatMessage(WebSocketSession session, ChatMessage message) {
        String sessionId = session.getId();
        UserSession userSession = activeSessions.get(sessionId);
        
        if (userSession != null && userSession.getUsername() != null) {
            // 设置消息的用户名（防止客户端伪造）
            message.setUsername(userSession.getUsername());
            message.setType("CHAT");
            message.setTimestamp(java.time.Instant.now());
            
            // 添加到消息历史
            addToMessageHistory(message);
            
            // 广播消息给所有用户
            broadcastMessage(message);
            
            logger.info("聊天消息: " + userSession.getUsername() + " -> " + message.getMessage());
        } else {
            sendErrorMessage(session, "请先加入聊天室");
        }
    }
    
    /**
     * 处理用户离开聊天室
     */
    public void handleUserLeave(WebSocketSession session) {
        String sessionId = session.getId();
        UserSession userSession = activeSessions.get(sessionId);
        
        if (userSession != null) {
            String username = userSession.getUsername();
            
            // 移除会话
            activeSessions.remove(sessionId);
            if (username != null) {
                usernameToSessionId.remove(username);
                
                // 创建离开消息
                ChatMessage leaveMessage = ChatMessage.createLeaveMessage(username);
                addToMessageHistory(leaveMessage);
                
                // 广播用户离开消息
                broadcastMessage(leaveMessage);
                
                // 广播更新的用户列表
                broadcastUserList();
                
                logger.info("用户离开: " + username + " (会话: " + sessionId + ")");
            } else {
                logger.info("匿名会话离开: " + sessionId);
            }
        }
    }
    
    /**
     * 广播消息给所有在线用户
     */
    private void broadcastMessage(ChatMessage message) {
        String messageJson;
        try {
            messageJson = objectMapper.writeValueAsString(message);
        } catch (Exception e) {
            logger.severe("序列化消息失败: " + e.getMessage());
            return;
        }
        
        TextMessage textMessage = new TextMessage(messageJson);
        
        // 获取所有有效会话的副本，避免并发修改异常
        List<UserSession> validSessions = activeSessions.values().stream()
                .filter(UserSession::isValid)
                .collect(Collectors.toList());
        
        for (UserSession userSession : validSessions) {
            try {
                userSession.getWebSocketSession().sendMessage(textMessage);
            } catch (IOException e) {
                logger.warning("发送消息失败给用户: " + userSession.getUsername() + ", 错误: " + e.getMessage());
                // 移除无效会话
                removeInvalidSession(userSession);
            }
        }
    }
    
    /**
     * 广播在线用户列表
     */
    private void broadcastUserList() {
        List<String> onlineUsers = activeSessions.values().stream()
                .filter(session -> session.getUsername() != null && session.isValid())
                .map(UserSession::getUsername)
                .sorted()
                .collect(Collectors.toList());
        
        ChatMessage userListMessage = ChatMessage.createUserListMessage(onlineUsers);
        broadcastMessage(userListMessage);
    }
    
    /**
     * 发送消息历史给指定用户
     */
    private void sendMessageHistory(WebSocketSession session) {
        synchronized (messageHistory) {
            for (ChatMessage message : messageHistory) {
                try {
                    String messageJson = objectMapper.writeValueAsString(message);
                    session.sendMessage(new TextMessage(messageJson));
                } catch (IOException e) {
                    logger.warning("发送历史消息失败: " + e.getMessage());
                    break;
                }
            }
        }
    }
    
    /**
     * 发送错误消息给指定用户
     */
    private void sendErrorMessage(WebSocketSession session, String errorMsg) {
        try {
            ChatMessage errorMessage = new ChatMessage();
            errorMessage.setType("ERROR");
            errorMessage.setMessage(errorMsg);
            errorMessage.setTimestamp(java.time.Instant.now());
            
            String json = objectMapper.writeValueAsString(errorMessage);
            session.sendMessage(new TextMessage(json));
        } catch (IOException e) {
            logger.severe("发送错误消息失败: " + e.getMessage());
        }
    }
    
    /**
     * 添加消息到历史记录
     */
    private void addToMessageHistory(ChatMessage message) {
        synchronized (messageHistory) {
            messageHistory.add(message);
            // 保持历史记录在限制范围内
            if (messageHistory.size() > MAX_MESSAGE_HISTORY) {
                messageHistory.remove(0);
            }
        }
    }
    
    /**
     * 移除无效会话
     */
    private void removeInvalidSession(UserSession userSession) {
        String sessionId = userSession.getSessionId();
        String username = userSession.getUsername();
        
        activeSessions.remove(sessionId);
        if (username != null) {
            usernameToSessionId.remove(username);
        }
        
        logger.info("移除无效会话: " + sessionId);
    }
    
    /**
     * 获取在线用户数量
     */
    public int getOnlineUserCount() {
        return (int) activeSessions.values().stream()
                .filter(session -> session.getUsername() != null && session.isValid())
                .count();
    }
    
    /**
     * 获取在线用户列表
     */
    public List<String> getOnlineUsers() {
        return activeSessions.values().stream()
                .filter(session -> session.getUsername() != null && session.isValid())
                .map(UserSession::getUsername)
                .sorted()
                .collect(Collectors.toList());
    }
}